package cn.com.ejiakanghu.service;

import cn.com.ejiakanghu.core.config.DirectExchangeRabbitMQConfig;
import cn.com.ejiakanghu.core.exceptions.BizException;
import cn.com.ejiakanghu.core.vo.BaseResult;
import cn.com.ejiakanghu.dto.LeaseRefundData;
import cn.com.ejiakanghu.tools.OrderFeeExtNameEnum;
import org.apache.commons.lang.StringUtils;
import org.linlinjava.litemall.core.tool.wxpayscore.WxPayScoreTool;
import org.linlinjava.litemall.core.util.JacksonUtil;
import org.linlinjava.litemall.db.dao.LitemallOrderGoodsMapper;
import org.linlinjava.litemall.db.dao.LitemallOrderItemMapper;
import org.linlinjava.litemall.db.dao.LitemallOrderMapper;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.AgedmallWxNoDepositService;
import org.linlinjava.litemall.db.service.LitemallOrderGoodsService;
import org.linlinjava.litemall.db.service.LitemallOrderService;
import org.linlinjava.litemall.db.service.oder_manage.AgedMallOrderDbService;
import org.linlinjava.litemall.db.util.OrderGoodsConstant;
import org.linlinjava.litemall.db.util.OrderUtil;
import org.linlinjava.litemall.db.vo.order_manage.OrderCodeInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitMessagingTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 租赁订单服务
 * 预付金：A元（用户下单时支付的总金额）
 * 归还后（扣除以下费用X元）
 * 1、配送
 * 配送方式：送货配送送货运费：x元 或租赁满Z天免收x元
 * 配送方式：加急配送/感谢费：x元 （不满足加急钱需要退还）
 * 配送方式：预约配送：x元
 * 配送方式：自提：0元
 * 配送方式：取件运费：x元 或租赁满租赁满Z天免收x元
 * 2、租金
 * 当前租金：x元
 * 3、服务
 * 服务费用：x元 或租赁满足Z天免收x元/下单赠送
 * 4、可选配件/必选配件
 * 配件费用：x元 或租赁满租赁满Z天免收x元
 * 5、包材费：x元 （用户没有返还的情况的下，需要扣除这一笔费用）
 * 6、清洁费：x元
 * 7、抵扣金：x元
 * 计算公式：（预付金+抵扣金）➖（租金+配送运费+服务费+清洁费+包材费+配件费）=应退金额
 *
 * @author houzb
 * @Description
 * @create 2021-11-24 15:54
 */
@Service
public class LeaseOrderService {
    private Logger logger = LoggerFactory.getLogger(LeaseOrderService.class);

    @Autowired
    private OrderCalcService orderCalcService;
    @Autowired
    private AgedMallOrderDbService agedMallOrderDbService;
    @Autowired
    private RabbitMessagingTemplate rabbitMessagingTemplate;
    @Autowired
    private LitemallOrderService litemallOrderService;
    @Autowired
    private AgedmallWxNoDepositService agedmallWxNoDepositService;
    @Autowired
    private WxPayScoreTool wxPayScoreTool;
    @Autowired
    private LitemallOrderGoodsService litemallOrderGoodsService;
    @Autowired
    private LitemallOrderGoodsMapper litemallOrderGoodsMapper;
    @Autowired
    private LitemallOrderItemMapper litemallOrderItemMapper;
    @Autowired
    private LitemallOrderMapper litemallOrderMapper;

    /**
     * 归还设备后订单结算,返回需要退还的费用
     *
     * @param bigOrderCode
     * @param itemOrderCode
     * @return
     */
    @Transactional
    public BigDecimal orderSettlementCal(String bigOrderCode, String itemOrderCode) {
        LitemallOrder bigOrder = litemallOrderService.findOrderByOrderCode(bigOrderCode);
        if (bigOrder == null) {
            logger.error("结算订单，订单不存在{}，{}", bigOrderCode, itemOrderCode);
            return null;
        }
        Integer isCredit = bigOrder.getIsCredit();
        //是否为免押订单 true免押订单,false 费免押订单
        boolean isNoDeposit = isCredit != null && isCredit == 1;

        LeaseRefundData leaseRefundData = orderCalcService.calLeaseOrderSettlementRefund(bigOrderCode, itemOrderCode);
        //免押订单无需退款操作
        BigDecimal refundFee = isNoDeposit ? BigDecimal.ZERO : leaseRefundData.getRefundFee();
        BigDecimal totalFee = leaseRefundData.getTotalFee();
        BigDecimal costFee = leaseRefundData.getCostFee();
        BigDecimal rent = leaseRefundData.getRent();
        BigDecimal deliverFee = leaseRefundData.getDeliverFee();
        logger.debug("结算租赁结算rst:{},{},{},{},{}, {}", bigOrderCode, itemOrderCode, totalFee, costFee, refundFee, isNoDeposit);

        //更新应付租金及实际退款金额
        agedMallOrderDbService.updateChildOrderPayRentAndRefund(itemOrderCode, rent, refundFee, deliverFee);

        if (isNoDeposit) {
            //更新免押订单子单需要扣除的费用，待全部计算完后进行免押订单的完结并扣除全部费用
            agedmallWxNoDepositService.updateNoDepositPayFee(bigOrderCode, itemOrderCode, null, costFee);
            //订单是否全部结算
            long noSettleCount = agedmallWxNoDepositService.getNoDepositNoSettleCount(bigOrderCode);
            if (noSettleCount == 0) {
                //已全部结算，针对免押订单进行完结
                BigDecimal totalCostFee = agedmallWxNoDepositService.getNoDepositTotalCostFee(bigOrderCode);
                logger.debug("免押子订单全部结算完，调用完结免押订单扣除消费费用:{},{}", bigOrderCode, totalCostFee);
                //调用信用免押完结订单进行扣款
                LitemallOrderGoods orderGoods = litemallOrderGoodsService.getOrderGoodsByChildOrderCode(itemOrderCode);
                LocalDateTime signTime = orderCalcService.getUserSignTime(orderGoods);
                BaseResult comRst = wxPayScoreTool.payScoreComplete(bigOrderCode, totalCostFee, signTime);
                logger.debug("免押完结结果:{},{}", bigOrderCode, comRst);
            }
        }

        return refundFee;
    }

    /**
     * 归还设备后订单结算,返回需要退还的费用
     *
     * @param bigOrderCode
     * @param itemOrderCode
     * @return
     */
    public BigDecimal buyOutorderSettlementCal(String bigOrderCode, String itemOrderCode, BigDecimal buyOutPrice) {

        LeaseRefundData leaseRefundData = orderCalcService.orderSettlementAfterBuyingOutTheEquipment(bigOrderCode, itemOrderCode, buyOutPrice);
        //退还金额
        BigDecimal refundFee = leaseRefundData.getRefundFee();
        //用户抵扣金 预付金
        BigDecimal totalFee = leaseRefundData.getTotalFee();
        //总费用
        BigDecimal costFee = leaseRefundData.getCostFee();
        //租金
        BigDecimal rent = leaseRefundData.getRent();
        //运费
        BigDecimal deliverFee = leaseRefundData.getDeliverFee();
        logger.debug("结算租赁结算rst:{},{},{},{},{}", bigOrderCode, itemOrderCode, totalFee, costFee, refundFee);

        //更新应付租金及实际退款金额
        agedMallOrderDbService.buyoutUpdateChildOrderPayRentAndRefund(itemOrderCode, rent, refundFee, deliverFee, buyOutPrice);

        return refundFee;
    }


    /**
     * 根据归还的设备进行结算计算
     *
     * @param rfid
     * @param uid
     * @return
     */
    public void orderSettlementByEqu(String rfid, long uid) {
        if (StringUtils.isBlank(rfid)) {
            throw new BizException("结算参数rfid 为空");
        }
        if (uid <= 0) {
            throw new BizException("结算参数用户id 不正确");
        }
        //获取大订单号，子订单号
        OrderCodeInfo orderCodeInfo = agedMallOrderDbService.getUserLeaseApplyBackOrderInfo(uid, rfid);
        if (orderCodeInfo == null) {
            throw new BizException("结算获取订单号信息不存在");
        }
        String bigOrderCode = orderCodeInfo.getOrderCode();
        String itemOrderCode = orderCodeInfo.getChildOrderCode();
        BigDecimal refundFee = orderSettlementCal(bigOrderCode, itemOrderCode);
        Map<String, Object> refundData = new HashMap<>();
        refundData.put("refundMoney", refundFee);
        refundData.put("bigOrderCode", bigOrderCode);
    }

    /**
     * 订单结算  退款
     * 如果是支付免押判断是否全部归还完成，归还完成则进行支付分完结调用
     */
    public void orderSettlementRefund(String bigOrderCode, String childOrderCode) {
        LeaseRefundData leaseRefundData = orderCalcService.orderSettlementCalRefund(bigOrderCode, childOrderCode);
        System.out.println("refundFees" + leaseRefundData.getRefundFee());
        if (leaseRefundData.getRefundFee().doubleValue() <= 0) {
            return;
        }
        Map<String, Object> refundData = new HashMap<>();
        refundData.put("refundMoney", leaseRefundData.getRefundFee());
        refundData.put("bigOrderCode", bigOrderCode);
        refundData.put("childOrderCode", childOrderCode);
        logger.debug("订单退款{},{},{}", bigOrderCode, childOrderCode, leaseRefundData.getRefundFee());
        rabbitMessagingTemplate.convertAndSend(DirectExchangeRabbitMQConfig.QUEUE_WX_REFUND, JacksonUtil.toJson(refundData));
    }

    /**
     * 订单结算
     * 如果是支付免押判断是否全部归还完成，归还完成则进行支付分完结调用
     *
     * @param bigOrderCode
     * @param childOrderCode
     */
    public void orderSettlement(String bigOrderCode, String childOrderCode) {
        logger.debug("结算租赁订单:{},{}", bigOrderCode, childOrderCode);
        BigDecimal refundFee = orderSettlementCal(bigOrderCode, childOrderCode);
        logger.debug("结算租赁订单可退金额:{},{},{}", bigOrderCode, childOrderCode, refundFee);
        if (refundFee.doubleValue() <= 0) {
            return;
        }
        Map<String, Object> refundData = new HashMap<>();
        refundData.put("refundMoney", refundFee);
        refundData.put("bigOrderCode", bigOrderCode);
        refundData.put("childOrderCode", childOrderCode);
        rabbitMessagingTemplate.convertAndSend(DirectExchangeRabbitMQConfig.QUEUE_WX_REFUND, JacksonUtil.toJson(refundData));
    }


    /**
     * 买断
     * 订单结算
     * 如果是支付免押判断是否全部归还完成，归还完成则进行支付分完结调用
     *
     * @param bigOrderCode
     * @param childOrderCode
     */
    public void BuyOutOrderSettlement(String bigOrderCode, String childOrderCode, BigDecimal totalPrice) {
        logger.debug("结算租赁订单:{},{}", bigOrderCode, childOrderCode);
        BigDecimal refundFee = buyOutOrderSettlementCal(bigOrderCode, childOrderCode, totalPrice);
        logger.debug("结算租赁订单可退金额:{},{},{}", bigOrderCode, childOrderCode, refundFee);
        if (refundFee.doubleValue() <= 0) {
            return;
        }
        Map<String, Object> refundData = new HashMap<>();
        refundData.put("refundMoney", refundFee);
        refundData.put("bigOrderCode", bigOrderCode);
        refundData.put("childOrderCode", childOrderCode);
        rabbitMessagingTemplate.convertAndSend(DirectExchangeRabbitMQConfig.QUEUE_WX_REFUND, JacksonUtil.toJson(refundData));
    }


    /**
     * 买断 设备后订单结算,返回需要退还的费用
     *
     * @param bigOrderCode
     * @param itemOrderCode
     * @return
     */
    @Transactional
    public BigDecimal buyOutOrderSettlementCal(String bigOrderCode, String itemOrderCode, BigDecimal totalPrice) {
        LitemallOrder bigOrder = litemallOrderService.findOrderByOrderCode(bigOrderCode);
        if (bigOrder == null) {
            logger.error("结算订单，订单不存在{}，{}", bigOrderCode, itemOrderCode);
            return null;
        }
        Integer isCredit = bigOrder.getIsCredit();
        //是否为免押订单 true免押订单,false 费免押订单
        boolean isNoDeposit = isCredit != null && isCredit == 1;

        LeaseRefundData leaseRefundData = orderCalcService.buyOutCalLeaseOrderSettlementRefund(bigOrderCode, itemOrderCode, totalPrice);
        //免押订单无需退款操作
        BigDecimal refundFee = isNoDeposit ? BigDecimal.ZERO : leaseRefundData.getRefundFee();
        BigDecimal totalFee = leaseRefundData.getTotalFee();
        BigDecimal costFee = leaseRefundData.getCostFee();
        BigDecimal rent = leaseRefundData.getRent();
        BigDecimal deliverFee = leaseRefundData.getDeliverFee();
        logger.debug("结算租赁结算rst:{},{},{},{},{}, {}", bigOrderCode, itemOrderCode, totalFee, costFee, refundFee, isNoDeposit);

        //更新应付租金及实际退款金额
        agedMallOrderDbService.updateChildOrderPayRentAndRefund(itemOrderCode, rent, refundFee, deliverFee);

        if (isNoDeposit) {
            //更新免押订单子单需要扣除的费用，待全部计算完后进行免押订单的完结并扣除全部费用
            agedmallWxNoDepositService.updateNoDepositPayFee(bigOrderCode, itemOrderCode, null, costFee);
            //订单是否全部结算
            long noSettleCount = agedmallWxNoDepositService.getNoDepositNoSettleCount(bigOrderCode);
            if (noSettleCount == 0) {
                //已全部结算，针对免押订单进行完结
                BigDecimal totalCostFee = agedmallWxNoDepositService.getNoDepositTotalCostFee(bigOrderCode);
                logger.debug("免押子订单全部结算完，调用完结免押订单扣除消费费用:{},{}", bigOrderCode, totalCostFee);
                //调用信用免押完结订单进行扣款
                LitemallOrderGoods orderGoods = litemallOrderGoodsService.getOrderGoodsByChildOrderCode(itemOrderCode);
                LocalDateTime signTime = orderCalcService.getUserSignTime(orderGoods);
                BaseResult comRst = wxPayScoreTool.payScoreComplete(bigOrderCode, totalCostFee, signTime);
                logger.debug("免押完结结果:{},{}", bigOrderCode, comRst);
            }
        }

        return refundFee;
    }


    /**
     * 买断订单结算
     *
     * @param bigOrderCode
     * @param childOrderCode
     */
    public void buyOutorderSettlement(String bigOrderCode, String childOrderCode, BigDecimal buyOutPrice) {
        logger.debug("结算租赁订单:{},{}", bigOrderCode, childOrderCode);
        BigDecimal refundFee = buyOutorderSettlementCal(bigOrderCode, childOrderCode, buyOutPrice);
        logger.debug("结算租赁订单可退金额:{},{},{}", bigOrderCode, childOrderCode, refundFee);
        if (refundFee.doubleValue() <= 0) {
            System.out.println("--->" + refundFee.doubleValue());
            return;
        }
        Map<String, Object> refundData = new HashMap<>();
        refundData.put("refundMoney", refundFee);
        refundData.put("bigOrderCode", bigOrderCode);
        refundData.put("childOrderCode", childOrderCode);
        System.out.println("==========>" + refundFee);
        rabbitMessagingTemplate.convertAndSend(DirectExchangeRabbitMQConfig.QUEUE_WX_REFUND, JacksonUtil.toJson(refundData));
    }

}
